iT邦幫忙

2024 iThome 鐵人賽

DAY 8
0
Modern Web

Laravel 那麼好用還需要自幹框架嗎系列 第 8

Day 08:Laravel 怎麼處理請求

  • 分享至 

  • xImage
  •  

看完怎麼建立路由之後,我們來看看當使用者發出請求時,Laravel 會怎麼進行處理。

使用者發出的請求,都會經過 public/index.php 裡面

use Illuminate\Http\Request;

//...

// Bootstrap Laravel and handle the request...
(require_once __DIR__.'/../bootstrap/app.php')
    ->handleRequest(Request::capture());

的這段程式。

這段會呼叫到 ApplicationhandleRequest()

我們來看看其實作內容

/**
 * Handle the incoming HTTP request and send the response to the browser.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 */
public function handleRequest(Request $request)
{
	$kernel = $this->make(HttpKernelContract::class);

	$response = $kernel->handle($request)->send();

	$kernel->terminate($request, $response);
}

如果和以前的 Laravel 框架比較,會發現這一段似乎在哪邊看過。

其實這一段在以前的 Laravel 框架,是直接放在 public/index.php 裡面的,在最近的改版內才封裝在 ApplicationhandleRequest() 內。

在這邊, Laravel 先建立一個 $kernel 物件,透過 $kernelhandle() 將使用者請求轉換為 $response 之後,接著就是送出 $response 並將整個 $kernel 終止。

很單純對嗎?其實整個 Laravel 框架所做的事情就是這麼單純:接收請求、建立核心處理請求、回傳回應。

這邊的細節自然包含在 handle() 裡面:

/**
 * Handle an incoming HTTP request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function handle($request)
{
	$this->requestStartedAt = Carbon::now();

	try {
		$request->enableHttpMethodParameterOverride();

		$response = $this->sendRequestThroughRouter($request);
	} catch (Throwable $e) {
		$this->reportException($e);

		$response = $this->renderException($request, $e);
	}

	$this->app['events']->dispatch(
		new RequestHandled($request, $response)
	);

	return $response;
}

我們想要關注的是這段邏輯內怎麼將請求分配給路由,所以要看 sendRequestThroughRouter()

sendRequestThroughRouter() 的實作則是

/**
 * Send the given request through the middleware / router.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
protected function sendRequestThroughRouter($request)
{
	$this->app->instance('request', $request);

	Facade::clearResolvedInstance('request');

	$this->bootstrap();

	return (new Pipeline($this->app))
				->send($request)
				->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
				->then($this->dispatchToRouter());
}

這邊建立了一個 Pipeline 物件,並將 $request 送入

protected function dispatchToRouter()
{
	return function ($request) {
		$this->app->instance('request', $request);

		return $this->router->dispatch($request);
	};
}

這邊 dispatch() 的實作則是

/**
 * Dispatch the request to the application.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function dispatch(Request $request)
{
	$this->currentRequest = $request;

	return $this->dispatchToRoute($request);
}

/**
 * Dispatch the request to a route and return the response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function dispatchToRoute(Request $request)
{
	return $this->runRoute($request, $this->findRoute($request));
}

到這邊,我們已經追到相當細節的實作階段,在這個階段裡執行的事情就是路由要做的兩件事:找到對應路由、執行該路由要做的事情並回傳 Response 物件。


上一篇
Day 07:Laravel 如何建立路由物件
下一篇
Day 09:findRoute() 實作、SymfonyRoute
系列文
Laravel 那麼好用還需要自幹框架嗎18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言